package com.hk.web.core.config.mvc;

import com.hk.commons.serializer.JacksonObjMapper;
import com.hk.web.core.advice.IPLimitingAspect;
import com.hk.web.core.intercept.MonitorInterceptor;
import com.hk.web.core.processor.JsonModelAttributeMethodProcessor;
import org.apache.commons.codec.CharEncoding;
import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.annotation.Resource;
import javax.validation.Validation;
import javax.validation.ValidatorFactory;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;

@EnableAspectJAutoProxy(proxyTargetClass=true) //启用动态代理
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.hk.web.**.controller", "com.hk.**.service.**","com.hk.commons.**","com.hk.web.core.**.init"})
@Order(1)
public class WebMvcConfig implements WebMvcConfigurer {

    @Resource
    private StringHttpMessageConverter stringConverter;

    @Resource
    private MappingJackson2HttpMessageConverter jacksonConverter;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MonitorInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/resources/**");

    }

    //限流
    @Bean("ipLimitingAspect")
    public IPLimitingAspect ipLimitingAspect(){
        return IPLimitingAspect.getInstance();
    }
    /**
     * 配置方法级别验证
     */
    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class).configure()
                .failFast(true).buildValidatorFactory();
        MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
        processor.setValidatorFactory(validatorFactory);
        return processor;
    }

    //加载多环境资源
    @Bean("propertyConfigurer")
    public static PropertySourcesPlaceholderConfigurer propertyConfigurer() throws IOException {
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        PropertySourcesPlaceholderConfigurer propertyConfigurer = new PropertySourcesPlaceholderConfigurer();
        propertyConfigurer.setLocations(resolver.getResources("classpath*:../../../../config/*.properties"));
        propertyConfigurer.setFileEncoding(CharEncoding.UTF_8);
        return propertyConfigurer;
    }

    /**
     * 自定义http消息转换器
     */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        stringConverter.setWriteAcceptCharset(false);
        stringConverter.setDefaultCharset(StandardCharsets.UTF_8);
        converters.add(stringConverter);
        jacksonConverter.setObjectMapper(new JacksonObjMapper());
        converters.add(jacksonConverter);
    }

    /**
     * 静态资源访问
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/swagger-ui.html").addResourceLocations("/swagger-ui.html");
        registry.addResourceHandler("/webjars/**").addResourceLocations("/webjars/");
        registry.addResourceHandler("/swagger-resources/**").addResourceLocations("/swagger-resources/");
        registry.addResourceHandler("/v2/**").addResourceLocations("/v2/");
    }

    /**
     * 参数解析器
     */
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new JsonModelAttributeMethodProcessor(true, jacksonConverter));
    }

}
